#include "SQLParserUtils.h"

#include "../../utils/StringUtils.h"
#include "../dialect/mysql/parser/MySqlStatementParser.h"
#include "../../utils/log.h"
#include "../dialect/mysql/parser/MySqlExprParser.h"
#include "../dialect/mysql/parser/MySqlLexer.h"
#include "../dialect/mysql/ast/statement/MySqlSelectQueryBlock.h"

SQLStatementParser_ptr SQLParserUtils::createSQLStatementParser(string_ptr sql, DbType_ptr dbType)
{
  SQLParserFeature_list_ptr features = std::make_shared<std::list<SQLParserFeature_ptr>>();
  if (DbType::odps.name->c_str() == dbType->name->c_str() ||
      DbType::mysql.name->c_str() == dbType->name->c_str())
  {
    features->push_back(SQLParserFeature_ptr(new SQLParserFeature(SQLParserFeature::KeepComments.mask, SQLParserFeature::KeepComments.name)));
    //     features = new SQLParserFeature[]{SQLParserFeature::KeepComments};
    // } else {
    //     features = new SQLParserFeature[]{};
  }
  return createSQLStatementParser(sql, dbType, features);
}

SQLStatementParser_ptr SQLParserUtils::createSQLStatementParser(string_ptr sql, DbType_ptr dbType, BOOL_ptr keepComments)
{
  SQLParserFeature_list_ptr features = std::make_shared<std::list<SQLParserFeature_ptr>>();
  if (keepComments)
  {
    features->push_back(SQLParserFeature_ptr(new SQLParserFeature(&SQLParserFeature::KeepComments)));
    //     features = new SQLParserFeature[]{SQLParserFeature.KeepComments};
    // } else {
    //     features = new SQLParserFeature[]{};
  }

  return createSQLStatementParser(sql, dbType, features);
}

// static SQLStatementParser* createSQLStatementParser(string_ptr  sql, DbType dbType, std::list<SQLParserFeature> features) {
//     return createSQLStatementParser(sql, dbType, features);
// }

SQLStatementParser_ptr SQLParserUtils::createSQLStatementParser(
    string_ptr sql,
    DbType_ptr dbType,
    SQLParserFeature_list_ptr features)
{
  if (dbType->name->empty())
  {
    dbType = DbType_ptr(new DbType(&DbType::other));
  }

  LOG_INFO << "dbType:" << dbType->name->c_str();

  if (*dbType == DbType::mysql ||
      *dbType == DbType::tidb ||
      *dbType == DbType::mariadb ||
      *dbType == DbType::drds)
  {
    LOG_INFO << "goto MySqlStatementParser";
    return MySqlStatementParser_ptr(new MySqlStatementParser(sql, features));
  }
  else if (*dbType == DbType::oracle ||
           *dbType == DbType::oceanbase_oracle)
  {
    // return new OracleStatementParser(sql, features);
  }
  else if (*dbType == DbType::elastic_search)
  {
    // MySqlStatementParser* parser = new MySqlStatementParser(sql, features);
    // parser.dbType = dbType;
    // parser.exprParser.dbType = dbType;
    // return parser;
  }
  else if (*dbType == DbType::postgresql ||
           *dbType == DbType::edb)
  {
    // return new PGSQLStatementParser(sql, features);
  }
  else if (*dbType == DbType::sqlserver ||
           *dbType == DbType::jtds)
  {
    // return new SQLServerStatementParser(sql, features);
  }
  else if (*dbType == DbType::h2)
  {
    // return new H2StatementParser(sql, features);
  }
  else if (*dbType == DbType::blink)
  {
    // return new BlinkStatementParser(sql, features);
  }
  else if (*dbType == DbType::db2)
  {
    // return new DB2StatementParser(sql, features);
  }
  else if (*dbType == DbType::odps)
  {
    // return new OdpsStatementParser(sql, features);
  }
  else if (*dbType == DbType::phoenix)
  {
    // return new PhoenixStatementParser(sql);
  }
  else if (*dbType == DbType::hive)
  {
    // return new HiveStatementParser(sql, features);
  }
  else if (*dbType == DbType::presto ||
           *dbType == DbType::trino)
  {
    // return new PrestoStatementParser(sql);
  }
  else if (*dbType == DbType::ads)
  {
    // return new AdsStatementParser(sql);
  }
  else if (*dbType == DbType::antspark)
  {
    // return new AntsparkStatementParser(sql);
  }
  else if (*dbType == DbType::clickhouse)
  {
    // return new ClickhouseStatementParser(sql);
  }
  else if (*dbType == DbType::starrocks)
  {
    // return new StarRocksStatementParser(sql);
  }
  else
  {
    LOG_INFO << "goto SQLStatementParser";
    return SQLStatementParser_ptr(new SQLStatementParser(sql, dbType));
  }
}

SQLExprParser_ptr SQLParserUtils::createExprParser(string_ptr sql, DbType_ptr dbType)
{
  SQLParserFeature_list_ptr tmp = std::make_shared<std::list<SQLParserFeature_ptr>>();
  return createExprParser(sql, dbType, tmp);
}

SQLExprParser_ptr SQLParserUtils::createExprParser(string_ptr sql, DbType_ptr dbType, SQLParserFeature_list_ptr features)
{
  if (dbType == NULL)
  {
    dbType = DbType_ptr(new DbType(&DbType::other));
  }

  if (dbType->name->c_str() == DbType::oracle.name->c_str())
  {
    // return new OracleExprParser(sql, features);
  }
  else if (dbType->name->c_str() == DbType::mysql.name->c_str() ||
           dbType->name->c_str() == DbType::mariadb.name->c_str())
  {
    return MySqlExprParser_ptr(new MySqlExprParser(sql, features));
  }
  else if (dbType->name->c_str() == DbType::elastic_search.name->c_str())
  {
    // MySqlExprParser parser = new MySqlExprParser(sql, features);
    // parser.dbType = dbType;
    // return parser;
  }
  else if (dbType->name->c_str() == DbType::h2.name->c_str())
  {
    //   // return new H2ExprParser(sql, features);
  }
  else if (dbType->name->c_str() == DbType::postgresql.name->c_str() ||
           dbType->name->c_str() == DbType::edb.name->c_str())
  {
    //   // return new PGExprParser(sql, features);
  }
  else if (dbType->name->c_str() == DbType::sqlserver.name->c_str() ||
           dbType->name->c_str() == DbType::jtds.name->c_str())
  {
    //   // return new SQLServerExprParser(sql, features);
  }
  else if (dbType->name->c_str() == DbType::db2.name->c_str())
  {
    //   // return new DB2ExprParser(sql, features);
  }
  else if (dbType->name->c_str() == DbType::odps.name->c_str())
  {
    //   // return new OdpsExprParser(sql, features);
  }
  else if (dbType->name->c_str() == DbType::phoenix.name->c_str())
  {
    //   // return new PhoenixExprParser(sql, features);
  }
  else if (dbType->name->c_str() == DbType::presto.name->c_str() ||
           dbType->name->c_str() == DbType::trino.name->c_str())
  {
    //   // return new PrestoExprParser(sql, features);
  }
  else if (dbType->name->c_str() == DbType::hive.name->c_str())
  {
    //   // return new HiveExprParser(sql, features);
  }
  else if (dbType->name->c_str() == DbType::clickhouse.name->c_str())
  {
    //   // return new ClickhouseExprParser(sql, features);
  }
  else if (dbType->name->c_str() == DbType::oscar.name->c_str())
  {
    //   // return new OscarExprParser(sql, features);
  }
  else if (dbType->name->c_str() == DbType::starrocks.name->c_str())
  {
    //   // return new StarRocksExprParser(sql, features);
  }
  else
  {
    return SQLExprParser_ptr(new SQLExprParser(sql, dbType, features));
  }
}

Lexer_ptr SQLParserUtils::createLexer(string_ptr sql, DbType_ptr dbType)
{
  SQLParserFeature_list_ptr features_ = std::make_shared<std::list<SQLParserFeature_ptr>>();
  return createLexer(sql, dbType, features_);
}

Lexer_ptr SQLParserUtils::createLexer(string_ptr sql, DbType_ptr dbType, SQLParserFeature_list_ptr features)
{
  if (dbType == NULL)
  {
    dbType = DbType_ptr(new DbType(&DbType::other));
  }

  if (dbType->name->c_str() == DbType::oracle.name->c_str())
  {
    //         // return new OracleLexer(sql, features);
  }
  else if (dbType->name->c_str() == DbType::mysql.name->c_str() ||
           dbType->name->c_str() == DbType::mariadb.name->c_str())
  {
    return MySqlLexer_ptr(new MySqlLexer(sql, features));
  }
  else if (dbType->name->c_str() == DbType::elastic_search.name->c_str())
  {
    //         // MySqlLexer lexer = new MySqlLexer(sql, features);
    //         // lexer.dbType = dbType;
    //         // return lexer;
    //     }
  }
  else if (dbType->name->c_str() == DbType::h2.name->c_str())
  {
    //         // return new H2Lexer(sql, features);
  }
  else if (dbType->name->c_str() == DbType::postgresql.name->c_str() ||
           dbType->name->c_str() == DbType::edb.name->c_str())
  {
    //         // return new PGLexer(sql, features);
  }
  else if (dbType->name->c_str() == DbType::db2.name->c_str())
  {
    //         // return new DB2Lexer(sql, features);
  }
  else if (dbType->name->c_str() == DbType::odps.name->c_str())
  {
    //         // return new OdpsLexer(sql, features);
  }
  else if (dbType->name->c_str() == DbType::phoenix.name->c_str())
  {
    //         // return new PhoenixLexer(sql, features);
  }
  else if (dbType->name->c_str() == DbType::presto.name->c_str() ||
           dbType->name->c_str() == DbType::trino.name->c_str())
  {
    //         // return new PrestoLexer(sql, features);
  }
  else if (dbType->name->c_str() == DbType::antspark.name->c_str())
  {
    //         // return new AntsparkLexer(sql);
  }
  else if (dbType->name->c_str() == DbType::oscar.name->c_str())
  {
    //         // return new OscarLexer(sql, features);
  }
  else if (dbType->name->c_str() == DbType::clickhouse.name->c_str())
  {
    //         // return new ClickhouseLexer(sql, features);
  }
  else if (dbType->name->c_str() == DbType::starrocks.name->c_str())
  {
    //         // return new StarRocksLexer(sql, features);
  }
  else
  {
    //         Lexer_ptr  lexer = new Lexer(sql, NULL, dbType);
    //         for (SQLParserFeature feature : features) {
    //             lexer->config(feature, BOOL::TRUE);
    //         }
    //         return lexer;
    //     }
  }

  Lexer_ptr lexer = Lexer_ptr(new Lexer(encode_util::UTF8ToUnicode(sql->c_str()), nullptr, dbType));
  return lexer;
}

SQLSelectQueryBlock *SQLParserUtils::createSelectQueryBlock(DbType_ptr dbType)
{
  if (dbType == NULL)
  {
    dbType = DbType_ptr(new DbType(&DbType::other));
  }

  if (dbType->name->c_str() == DbType::mysql.name->c_str())
  {
    return new MySqlSelectQueryBlock();
  }
  else if (dbType->name->c_str() == DbType::oracle.name->c_str())
  {
    //   // return new OracleSelectQueryBlock();
  }
  else if (dbType->name->c_str() == DbType::db2.name->c_str())
  {
    //   // return new DB2SelectQueryBlock();
  }
  else if (dbType->name->c_str() == DbType::postgresql.name->c_str())
  {
    //   // return new PGSelectQueryBlock();
  }
  else if (dbType->name->c_str() == DbType::odps.name->c_str())
  {
    //   // return new OdpsSelectQueryBlock();
  }
  else if (dbType->name->c_str() == DbType::sqlserver.name->c_str())
  {
    //   // return new SQLServerSelectQueryBlock();
  }
  else if (dbType->name->c_str() == DbType::oscar.name->c_str())
  {
    //   // return new OscarSelectQueryBlock();
  }
  else
  {
    return new SQLSelectQueryBlock(dbType);
  }
}

// static SQLType* getSQLType(string_ptr  sql, DbType dbType) {
//     Lexer_ptr  lexer = createLexer(sql, dbType);
//     return lexer.scanSQLType();
// }

// static SQLType* getSQLTypeV2(string_ptr  sql, DbType dbType) {
//     Lexer_ptr  lexer = createLexer(sql, dbType);
//     return lexer.scanSQLTypeV2();
// }

// static BOOL_ptr startsWithHint(string_ptr  sql, DbType dbType) {
//     Lexer lexer = createLexer(sql, dbType);
//     lexer.nextToken();
//     return lexer.token() == Token.HINT;
// }

// static BOOL_ptr containsAny(string_ptr  sql, DbType dbType, Token token) {
//     Lexer lexer = createLexer(sql, dbType);
//     for (; ; ) {
//         lexer.nextToken();
//         final Token tok = lexer.token;
//         switch (tok) {
//             case XEOF:
//             case ERROR:
//                 return BOOL::FALSE;
//             default:
//                 if (tok == token) {
//                     return BOOL::TRUE;
//                 }
//                 break;
//         }
//     }
// }

// static BOOL_ptr containsAny(string_ptr  sql, DbType dbType, Token token1, Token token2) {
//     Lexer lexer = createLexer(sql, dbType);
//     for (; ; ) {
//         lexer.nextToken();
//         final Token tok = lexer.token;
//         switch (tok) {
//             case XEOF:
//             case ERROR:
//                 return BOOL::FALSE;
//             default:
//                 if (tok == token1 || tok == token2) {
//                     return BOOL::TRUE;
//                 }
//                 break;
//         }
//     }
// }

// static BOOL_ptr containsAny(string_ptr  sql, DbType dbType, Token token1, Token token2, Token token3) {
//     Lexer lexer = createLexer(sql, dbType);
//     for (; ; ) {
//         lexer.nextToken();
//         final Token tok = lexer.token;
//         switch (tok) {
//             case XEOF:
//             case ERROR:
//                 return BOOL::FALSE;
//             default:
//                 if (tok == token1 || tok == token2 || tok == token3) {
//                     return BOOL::TRUE;
//                 }
//                 break;
//         }
//     }
// }

// static BOOL_ptr containsAny(string_ptr  sql, DbType dbType, std::list<Token> tokens) {
//     if (tokens == NULL) {
//         return BOOL::FALSE;
//     }

//     Lexer lexer = createLexer(sql, dbType);
//     for (; ; ) {
//         lexer.nextToken();
//         final Token tok = lexer.token;
//         switch (tok) {
//             case XEOF:
//             case ERROR:
//                 return BOOL::FALSE;
//             default:
//                 for (int i = 0; i < tokens.length; i++) {
//                     if (tokens[i] == tok) {
//                         return BOOL::TRUE;
//                     }
//                 }
//                 break;
//         }
//     }
// }

// Object_ptr  SQLParserUtils::getSimpleSelectValue(string_ptr  sql, DbType dbType) {
//     return getSimpleSelectValue(sql, dbType, NULL);
// }

// static Object_ptr  getSimpleSelectValue(string_ptr  sql, DbType dbType, SimpleValueEvalHandler handler) {
//     Lexer lexer = createLexer(sql, dbType);
//     lexer.nextToken();

//     if (lexer.token != Token.SELECT && lexer.token != Token.VALUES) {
//         return NULL;
//     }

//     lexer.nextTokenValue();

//     SQLExpr_ptr expr = NULL;
//     Object_ptr  value;
//     switch (lexer.token) {
//         case LITERAL_INT:
//             value = lexer.integerValue();
//             break;
//         case LITERAL_CHARS:
//         case LITERAL_NCHARS:
//             value = lexer.stringVal();
//             break;
//         case LITERAL_FLOAT:
//             value = lexer.decimalValue();
//             break;
//         default:
//             if (handler == NULL) {
//                 return NULL;
//             }

//             expr = new SQLExprParser(lexer).expr();
//             try {
//                 value = handler.eval(expr);
//             } catch (Exception error) {
//                 // skip
//                 value = NULL;
//             }
//             break;
//     }

//     lexer.nextToken();

//     if (lexer.token == Token.FROM) {
//         lexer.nextToken();
//         if (lexer.token == Token.DUAL) {
//             lexer.nextToken();
//         } else {
//             return NULL;
//         }
//     }
//     if (lexer.token != Token.XEOF) {
//         return NULL;
//     }

//     return value;
// }

// static string_ptr  replaceBackQuote(string_ptr  sql, DbType dbType) {
//     int i = sql.indexOf('`');

//     if (i == -1) {
//         return sql;
//     }

//     char[] chars = sql.toCharArray();
//     Lexer lexer = SQLParserUtils.createLexer(sql, dbType);

//     int len = chars.length;
//     int off = 0;

//     for_:
//     for (; ; ) {
//         lexer.nextToken();

//         int p0, p1;
//         char c0, c1;
//         switch (lexer.token) {
//             case IDENTIFIER:
//                 p0 = lexer.startPos + off;
//                 p1 = lexer.pos - 1 + off;
//                 c0 = chars[p0];
//                 c1 = chars[p1];
//                 if (c0 == '`' && c1 == '`') {
//                     if (p1 - p0 > 2 && chars[p0 + 1] == '\'' && chars[p1 - 1] == '\'') {
//                         System.arraycopy(chars, p0 + 1, chars, p0, p1 - p0 - 1);
//                         System.arraycopy(chars, p1 + 1, chars, p1 - 1, chars.length - p1 - 1);
//                         len -= 2;
//                         off -= 2;
//                     } else {
//                         chars[p0] = '"';
//                         chars[p1] = '"';
//                     }

//                 }
//                 break;
//             case XEOF:
//             case ERROR:
//                 break for_;
//             default:
//                 break;
//         }
//     }

//     return new string_ptr (chars, 0, len);
// }

// string_ptr  SQLParserUtils::addBackQuote(string_ptr  sql, DbType dbType) {
//     if (StringUtils.isEmpty(sql)) {
//         return sql;
//     }
//     SQLStatementParser* parser = createSQLStatementParser(sql, dbType);
//     StringBuffer buf = new StringBuffer(sql.length() + 20);
//     SQLASTOutputVisitor out = SQLUtils.createOutputVisitor(buf, DbType::mysql);
//     out.config(VisitorFeature.OutputNameQuote, BOOL::TRUE);

//     SQLType sqlType = getSQLType(sql, dbType);
//     if (sqlType == SQLType.INSERT) {
//         parser.config(SQLParserFeature.InsertReader, BOOL::TRUE);

//         SQLInsertStatement stmt = (SQLInsertStatement) parser.parseStatement();
//         int startPos = parser.getLexer().startPos;

//         stmt.accept(out);

//         if (stmt.getQuery() == NULL) {
//             buf.append(' ');
//             buf.append(sql, startPos, sql.length());
//         }
//     } else {
//         SQLStatement stmt = parser.parseStatement();
//         stmt.accept(out);
//     }

//     return buf.toString();
// }

// static std::list<string_ptr > split(string_ptr  sql, DbType dbType) {
//     if (dbType == NULL) {
//         dbType = DbType::other;
//     }

//     {
//         Lexer lexer = createLexer(sql, dbType);
//         lexer.nextToken();

//         BOOL_ptr script = BOOL::FALSE;
//         if (dbType == DbType::odps && lexer.token == Token.VARIANT) {
//             script = BOOL::TRUE;
//         }

//         if (script) {
//             return Collections.singletonList(sql);
//         }
//     }

//     std::list list = new ArrayList();

//     Lexer lexer = createLexer(sql, dbType);
//     lexer.config(SQLParserFeature.SkipComments, BOOL::FALSE);
//     lexer.config(SQLParserFeature.KeepComments, BOOL::TRUE);

//     BOOL_ptr set = BOOL::FALSE, paiOrJar = BOOL::FALSE;
//     int start = 0;
//     Token token = lexer.token;
//     for (; lexer.token != Token.XEOF; ) {
//         if (token == Token.SEMI) {
//             int len = lexer.startPos - start;
//             if (len > 0) {
//                 string_ptr  lineSql = sql.substring(start, lexer.startPos);
//                 lineSql = lineSql.trim();
//                 if (!lineSql.isEmpty()) {
//                     list.add(lineSql);
//                 }
//             }
//             start = lexer.startPos + 1;
//             set = BOOL::FALSE;
//         } else if (token == Token.CREATE) {
//             lexer.nextToken();

//             if (lexer.token == Token.FUNCTION || lexer.identifierEquals("FUNCTION")) {
//                 lexer.nextToken();
//                 lexer.nextToken();
//                 if (lexer.token == Token.AS) {
//                     lexer.nextToken();
//                     if (lexer.token == Token.LITERAL_CHARS) {
//                         lexer.nextToken();
//                         token = lexer.token;
//                         continue;
//                     }
//                 }
//                 lexer.startPos = sql.length();
//                 break;
//             }

//             token = lexer.token;
//             continue;
//         } else if (set && token == Token.EQ && dbType == DbType::odps) {
//             lexer.nextTokenForSet();
//             token = lexer.token;
//             continue;
//         }

//         if (lexer.identifierEquals("USING")) {
//             lexer.nextToken();
//             if (lexer.identifierEquals("jar")) {
//                 lexer.nextToken();
//             }
//         }

//         if (lexer.token == Token.SET) {
//             set = BOOL::TRUE;
//         }

//         if (lexer.identifierEquals("ADD") && (dbType == DbType::hive || dbType == DbType::odps)) {
//             lexer.nextToken();
//             if (lexer.identifierEquals("JAR")) {
//                 lexer.nextPath();
//             }
//         } else {
//             lexer.nextToken();
//         }
//         token = lexer.token;
//     }

//     if (start != sql.length() && token != Token.SEMI) {
//         int end = lexer.startPos;
//         if (end > sql.length()) {
//             end = sql.length();
//         }
//         string_ptr  splitSql = sql.substring(start, end).trim();
//         if (!paiOrJar) {
//             splitSql = removeComment(splitSql, dbType).trim();
//         } else {
//             if (splitSql.endsWith(";")) {
//                 splitSql = splitSql.substring(0, splitSql.length() - 1).trim();
//             }
//         }
//         if (!splitSql.isEmpty()) {
//             list.add(splitSql);
//         }
//     }

//     return list;
// }

// static std::list<string_ptr > splitAndRemoveComment(string_ptr  sql, DbType dbType) {
//     if (dbType == NULL) {
//         dbType = DbType::other;
//     }

//     BOOL_ptr containsCommentAndSemi = BOOL::FALSE;
//     {
//         Lexer lexer = createLexer(sql, dbType);
//         lexer.config(SQLParserFeature.SkipComments, BOOL::FALSE);
//         lexer.config(SQLParserFeature.KeepComments, BOOL::TRUE);

//         while (lexer.token != Token.XEOF) {
//             if (lexer.token == Token.LINE_COMMENT
//                     || lexer.token == Token.MULTI_LINE_COMMENT
//                     || lexer.token == Token.SEMI) {
//                 containsCommentAndSemi = BOOL::TRUE;
//                 break;
//             }
//             lexer.nextToken();
//         }

//         if (!containsCommentAndSemi) {
//             return Collections.singletonList(sql);
//         }
//     }

//     {
//         Lexer lexer = createLexer(sql, dbType);
//         lexer.nextToken();

//         BOOL_ptr script = BOOL::FALSE;
//         if (dbType == DbType::odps && lexer.token == Token.VARIANT) {
//             script = BOOL::TRUE;
//         }

//         if (script || lexer.identifierEquals("pai") || lexer.identifierEquals("jar") || lexer.identifierEquals("copy")) {
//             return Collections.singletonList(sql);
//         }
//     }

//     std::list list = new ArrayList();

//     Lexer lexer = createLexer(sql, dbType);
//     lexer.config(SQLParserFeature.SkipComments, BOOL::FALSE);
//     lexer.config(SQLParserFeature.KeepComments, BOOL::TRUE);

//     BOOL_ptr set = BOOL::FALSE, paiOrJar = BOOL::FALSE;
//     int start = 0;
//     Token preToken = NULL;
//     int prePos = 0;
//     Token token = lexer.token;
//     for (; lexer.token != Token.XEOF; ) {
//         if (token == Token.SEMI) {
//             int len = lexer.startPos - start;
//             if (len > 0) {
//                 string_ptr  lineSql = sql.substring(start, lexer.startPos);
//                 string_ptr  splitSql = set
//                         ? removeLeftComment(lineSql, dbType)
//                         : removeComment(lineSql, dbType
//                 ).trim();
//                 if (!splitSql.isEmpty()) {
//                     list.add(splitSql);
//                 }
//             }
//             start = lexer.startPos + 1;
//             set = BOOL::FALSE;
//         } else if (token == Token.MULTI_LINE_COMMENT) {
//             int len = lexer.startPos - start;
//             if (len > 0) {
//                 string_ptr  splitSql = removeComment(
//                         sql.substring(start, lexer.startPos),
//                         dbType
//                 ).trim();
//                 if (!splitSql.isEmpty()) {
//                     list.add(splitSql);
//                 }
//             }
//             lexer.nextToken();
//             token = lexer.token;
//             start = lexer.startPos;
//             continue;
//         } else if (token == Token.CREATE) {
//             lexer.nextToken();

//             if (lexer.token == Token.FUNCTION || lexer.identifierEquals("FUNCTION")) {
//                 lexer.nextToken();
//                 lexer.nextToken();
//                 if (lexer.token == Token.AS) {
//                     lexer.nextToken();
//                     if (lexer.token == Token.LITERAL_CHARS) {
//                         lexer.nextToken();
//                         token = lexer.token;
//                         continue;
//                     }
//                 }
//                 lexer.startPos = sql.length();
//                 break;
//             }

//             token = lexer.token;
//             continue;
//         } else if (set && token == Token.EQ && dbType == DbType::odps) {
//             lexer.nextTokenForSet();
//             token = lexer.token;
//             continue;
//         } else if (dbType == DbType::odps
//                 && (preToken == NULL || preToken == Token.LINE_COMMENT || preToken == Token.SEMI)
//                 && (lexer.identifierEquals("pai") || lexer.identifierEquals("jar") || lexer.identifierEquals("copy"))) {
//             lexer.scanLineArgument();
//             paiOrJar = BOOL::TRUE;
//         }

//         if (lexer.identifierEquals("USING")) {
//             lexer.nextToken();
//             if (lexer.identifierEquals("jar")) {
//                 lexer.nextToken();
//             }
//         }

//         if (lexer.token == Token.SET) {
//             set = BOOL::TRUE;
//         }

//         prePos = lexer.pos;
//         if (lexer.identifierEquals("ADD") && (dbType == DbType::hive || dbType == DbType::odps)) {
//             lexer.nextToken();
//             if (lexer.identifierEquals("JAR")) {
//                 lexer.nextPath();
//             }
//         } else {
//             lexer.nextToken();
//         }
//         preToken = token;
//         token = lexer.token;
//         if (token == Token.LINE_COMMENT
//                 && (preToken == Token.SEMI || preToken == Token.LINE_COMMENT || preToken == Token.MULTI_LINE_COMMENT)
//         ) {
//             start = lexer.pos;
//         }
//     }

//     if (start != sql.length() && token != Token.SEMI) {
//         int end = lexer.startPos;
//         if (end > sql.length()) {
//             end = sql.length();
//         }
//         string_ptr  splitSql = sql.substring(start, end).trim();
//         if (!paiOrJar) {
//             splitSql = removeComment(splitSql, dbType).trim();
//         } else {
//             if (splitSql.endsWith(";")) {
//                 splitSql = splitSql.substring(0, splitSql.length() - 1).trim();
//             }
//         }
//         if (!splitSql.isEmpty()) {
//             list.add(splitSql);
//         }
//     }

//     return list;
// }

// static string_ptr  removeLeftComment(string_ptr  sql, DbType dbType) {
//     if (dbType == NULL) {
//         dbType = DbType::other;
//     }

//     sql = sql.trim();
//     if (sql.startsWith("jar")) {
//         return sql;
//     }

//     BOOL_ptr containsComment = BOOL::FALSE;
//     {
//         Lexer lexer = createLexer(sql, dbType);
//         lexer.config(SQLParserFeature.SkipComments, BOOL::FALSE);
//         lexer.config(SQLParserFeature.KeepComments, BOOL::TRUE);

//         while (lexer.token != Token.XEOF) {
//             if (lexer.token == Token.LINE_COMMENT || lexer.token == Token.MULTI_LINE_COMMENT) {
//                 containsComment = BOOL::TRUE;
//                 break;
//             }
//             lexer.nextToken();
//         }

//         if (!containsComment) {
//             return sql;
//         }
//     }

//     StringBuilder sb = new StringBuilder();

//     Lexer lexer = createLexer(sql, dbType);
//     lexer.config(SQLParserFeature.SkipComments, BOOL::FALSE);
//     lexer.config(SQLParserFeature.KeepComments, BOOL::TRUE);
//     lexer.nextToken();

//     int start = 0;
//     for (; lexer.token != Token.XEOF; lexer.nextToken()) {
//         if (lexer.token == Token.LINE_COMMENT || lexer.token == Token.MULTI_LINE_COMMENT) {
//             continue;
//         }
//         start = lexer.startPos;
//         break;
//     }

//     if (start != sql.length()) {
//         sb.append(sql.substring(start, sql.length()));
//     }

//     return sb.toString();
// }

// static string_ptr  removeComment(string_ptr  sql, DbType dbType) {
//     if (dbType == NULL) {
//         dbType = DbType::other;
//     }

//     sql = sql.trim();
//     if (sql.startsWith("jar")) {
//         return sql;
//     }

//     if ((sql.startsWith("pai") || sql.startsWith("PAI")) && sql.indexOf(';') == -1) {
//         return sql;
//     }

//     BOOL_ptr containsComment = BOOL::FALSE;
//     {
//         Lexer lexer = createLexer(sql, dbType);
//         lexer.config(SQLParserFeature.SkipComments, BOOL::FALSE);
//         lexer.config(SQLParserFeature.KeepComments, BOOL::TRUE);

//         while (lexer.token != Token.XEOF) {
//             if (lexer.token == Token.LINE_COMMENT || lexer.token == Token.MULTI_LINE_COMMENT) {
//                 containsComment = BOOL::TRUE;
//                 break;
//             }
//             lexer.nextToken();
//         }

//         if (!containsComment) {
//             return sql;
//         }
//     }

//     StringBuilder sb = new StringBuilder();

//     Lexer lexer = createLexer(sql, dbType);
//     lexer.config(SQLParserFeature.SkipComments, BOOL::FALSE);
//     lexer.config(SQLParserFeature.KeepComments, BOOL::TRUE);

//     int start = 0;
//     Token token = lexer.token;
//     for (; lexer.token != Token.XEOF; ) {
//         if (token == Token.LINE_COMMENT) {
//             int len = lexer.startPos - start;
//             if (len > 0) {
//                 sb.append(sql.substring(start, lexer.startPos));
//             }
//             start = lexer.startPos + lexer.stringVal().length();
//         } else if (token == Token.MULTI_LINE_COMMENT) {
//             int len = lexer.startPos - start;
//             if (len > 0) {
//                 sb.append(sql.substring(start, lexer.startPos));
//             }
//             start = lexer.startPos + lexer.stringVal().length();
//         }

//         if (lexer.identifierEquals("ADD")) {
//             lexer.nextToken();
//             if (lexer.identifierEquals("JAR")) {
//                 lexer.nextPath();
//             }
//         } else {
//             lexer.nextToken();
//         }
//         token = lexer.token;
//     }

//     if (start != sql.length() && token != Token.LINE_COMMENT && token != Token.MULTI_LINE_COMMENT) {
//         sb.append(sql.substring(start, sql.length()));
//     }

//     return sb.toString();
// }

// static std::list<string_ptr > getTables(string_ptr  sql, DbType dbType) {
//     std::set<string_ptr > tables = new LinkedHashSet<>();

//     BOOL_ptr set = BOOL::FALSE;
//     Lexer lexer = createLexer(sql, dbType);
//     lexer.nextToken();

//     SQLExprParser exprParser;
//     switch (dbType) {
//         case odps:
//             exprParser = new OdpsExprParser(lexer);
//             break;
//         case mysql:
//             exprParser = new MySqlExprParser(lexer);
//             break;
//         default:
//             exprParser = new SQLExprParser(lexer);
//             break;
//     }

//     for_:
//     for (; lexer.token != Token.XEOF; ) {
//         switch (lexer.token) {
//             case CREATE:
//             case DROP:
//             case ALTER:
//                 set = BOOL::FALSE;
//                 lexer.nextToken();

//                 if (lexer.token == Token.TABLE) {
//                     lexer.nextToken();

//                     if (lexer.token == Token.IF) {
//                         lexer.nextToken();

//                         if (lexer.token == Token.NOT) {
//                             lexer.nextToken();
//                         }

//                         if (lexer.token == Token.EXISTS) {
//                             lexer.nextToken();
//                         }
//                     }

//                     SQLName name = exprParser.name();
//                     tables.add(name.toString());

//                     if (lexer.token == Token.AS) {
//                         lexer.nextToken();
//                     }
//                 }
//                 continue for_;
//             case FROM:
//             case JOIN:
//                 lexer.nextToken();
//                 if (lexer.token != Token.LPAREN
//                         && lexer.token != Token.VALUES
//                 ) {
//                     SQLName name = exprParser.name();
//                     tables.add(name.toString());
//                 }
//                 continue for_;
//             case SEMI:
//                 set = BOOL::FALSE;
//                 break;
//             case SET:
//                 set = BOOL::TRUE;
//                 break;
//             case EQ:
//                 if (set && dbType == DbType::.odps) {
//                     lexer.nextTokenForSet();
//                     continue for_;
//                 }
//                 break;
//             default:
//                 break;
//         }

//         lexer.nextToken();

//     }

//     return new ArrayList<>(tables);
// }
